﻿using System;
using System.Linq;
using Magnum.Pipeline;
using RestSharp;
using Wolfpack.Core;
using Wolfpack.Core.Interfaces;
using Wolfpack.Core.Interfaces.Entities;

namespace Wolfpack.Contrib.DashboardAdapter.Periscope
{
    public class PeriscopePushNotificationActivity : IActivityPlugin , IConsumer<WidgetUpdateRequest>
    {
        private RestClient _client;
        private readonly PeriscopePushNotificationActivityConfig _config;
        private readonly AgentConfiguration _agentConfig;

        public bool Enabled { get; set; }
        public Status Status { get; set; }

        public PluginDescriptor Identity
        {
            get
            {
                return new PluginDescriptor
                {
                    Name = _config.FriendlyId,
                    TypeId = new Guid("C323BAD4-693D-41B1-AD4A-AA12B24D4032"),
                    Description = "Pushes notification data to a Periscope dashboard"
                };
            }
        }

        public PeriscopePushNotificationActivity(PeriscopePushNotificationActivityConfig config,
            AgentConfiguration agentConfig)
        {
            _config = config;
            _agentConfig = agentConfig;

            Enabled = config.Enabled;
        }

        public void Initialise()
        {
            _client = new RestClient(_config.Url);
        }

        public void Start()
        {
            Messenger.Subscribe(this);
        }

        public void Stop()
        {
        }

        public void Pause()
        {
        }

        public void Continue()
        {
        }

        public void Consume(WidgetUpdateRequest message)
        {
            const string apiKeyHeader = "X-ApiKey";

            if (string.IsNullOrWhiteSpace(message.Origin))
                message.Origin = string.Format(@"{0}\{1}", _agentConfig.SiteId, _agentConfig.AgentId);


            var request = new RestRequest("dashboard/widget/update", Method.POST)
            {
                RequestFormat = DataFormat.Json
            };
            request.AddBody(message);

            if (!string.IsNullOrWhiteSpace(_config.ApiKey) &&
                !request.Parameters.Any(p => p.Type == ParameterType.HttpHeader &&
                    p.Name.Equals(apiKeyHeader, StringComparison.OrdinalIgnoreCase)))
            {
                request.AddHeader("X-ApiKey", _config.ApiKey);
            }

            try
            {
                var response = _client.Execute(request);
                AssertResponseStatus(response);
            }
            catch (Exception ex)
            {
                Logger.Error(Logger.Event.During(string.Format("Pushing update to widget '{0}' on dashboard '{1}' from '{2}'",
                    message.TargetWidgetId, _config.FriendlyId, message.Origin))
                    .Encountered(ex));
            }
        }

        private static void AssertResponseStatus(IRestResponse response)
        {
            if (response.ResponseStatus != ResponseStatus.Completed)
            {
                var msg = string.Format("General failure calling {0}, status: {1}, httpstatus: {2} ({3}), reason: {4}",
                                        response.ResponseUri,
                                        response.ResponseStatus,
                                        response.StatusCode,
                                        (int)response.StatusCode,
                                        response.ErrorMessage);
                throw new InvalidOperationException(msg);
            }

            if ((int)response.StatusCode < 400)
                return;

            throw new InvalidOperationException(string.Format("Http failure calling {0}, status: {1}, reason: {2}",
                response.ResponseUri,
                response.StatusCode,
                response.StatusDescription));
        }
    }
}